import sys
import time
import logging
import struct
import threading
from smap.driver import SmapDriver
from smap.loader import SmapLoadError
from smap.util import periodicSequentialCall
import datetime, calendar
from twisted.internet import threads, reactor
import csv
import os
from math import log

class NeomoteDriver(SmapDriver):
    def setup(self, opts):
        self.motenumbers = {'00-17-0d-00-00-3f-f9-89':1,
                            '00-17-0d-00-00-3f-f9-65':2,
                            '00-17-0d-00-00-3f-f9-37':3,
                            '00-17-0d-00-00-3f-f9-c2':4,
                            '00-17-0d-00-00-3f-f9-a9':5,
                            '00-17-0d-00-00-3f-f9-61':6,
                            '00-17-0d-00-00-3f-f9-a6':7,
                            '00-17-0d-00-00-3f-f9-40':8,
                            '00-17-0d-00-00-3f-f9-82':9,
                            '00-17-0d-00-00-3f-f9-32':10,
                            '00-17-0d-00-00-3f-f9-47':11,
                            '00-17-0d-00-00-3f-f9-64':12,
                            '00-17-0d-00-00-3f-f9-bf':13,
                            '00-17-0d-00-00-3f-f9-ad':14,
                            '00-17-0d-00-00-3f-f9-71':15,
                            '00-17-0d-00-00-3f-f9-35':16,
                            '00-17-0d-00-00-3f-f9-51':17,
                            '00-17-0d-00-00-3f-f9-b4':18,
                            '00-17-0d-00-00-3f-f9-5e':19,
                            '00-17-0d-00-00-3f-f9-58':20,
                            '00-17-0d-00-00-3f-f9-33':21}
        #print self.motenumbers
        #create all the data streams (m1c1, m1c2, m2c1, m2c2, etc)
        self.ids = {}
        self.calibrations = {}
        for motename in xrange(1, 22):
            self.ids[motename] = []
            self.calibrations[motename] = []
            for channel in xrange(1,13):
                w = (motename, channel)
                #print '/m%i/c%i' % w, opts.get('units_m%ic1' % motename, 'F')
                #print ('units_m%ic1' % motename).replace('c1', 'c' + str(channel))
                t = self.add_timeseries('/m%i/c%i' % w, opts.get(('units_m%ic1' % motename).replace('c1', 'c' + str(channel)), 'F'), data_type="double")
                self.ids[motename].append(t['uuid'])
                calFactor = float(opts.get("calFactor_m%ic%i" % w, '1'))
                calConstant = float(opts.get("calConstant_m%ic%i" % w, '0'))
                self.calibrations[motename].append((calFactor, calConstant))
        self.period = opts.get("Period", 30)
        #print self.ids
        #print self.calibrations

    def read(self):
        f = open(os.path.join(sys.path[0], '../data/current_data.csv'), 'r')
        data = csv.reader(f)
        for row in data:
            try:
                motename = self.motenumbers[row[0]]
                motetime = row[1]
                all_c_data = []
                t_pairs = []
                for channel in xrange(0,12):
                    c_data = float(row[channel+2])
                    #if c_data > 2147483647:
                    #    c_data = c_data - 4294967296
                    if channel == 1 or channel == 2 or channel == 5 or channel == 8 or channel == 9 or channel == 10:
                       t_pairs.append(c_data)
                    elif channel == 0:
                        all_c_data.append([channel, c_data])
                    else:
                        all_c_data.append([channel, c_data*6.144*2/1048576])
                r1 = t_pairs[0]/t_pairs[3]*10000
                r2 = t_pairs[1]/t_pairs[4]*10000
                r3 = t_pairs[2]/t_pairs[5]*10000
                #print [motename, t_pairs, r1,r2,r3]
                t1 = self._calc_temp(r1)
                t2 = self._calc_temp(r2)
                t3 = self._calc_temp(r3)
                all_c_data.extend([[1, t1], [2, t2], [5, t3]])
                #print all_c_data
                for dataset in all_c_data:
                    channel = dataset[0]
                    c_data = dataset[1]
                    #print [motename, channel+1, c_data]
                    self.add(self.ids[motename][channel], motetime, c_data*self.calibrations[motename][channel][0]+self.calibrations[motename][channel][1])
            except Exception as err:
                print "error in reading row: " + str(row) + str(err)
                pass
        os.remove(os.path.join(sys.path[0], '../data/current_data.csv'))
        f.close()
       
    def start(self):
        periodicSequentialCall(self.read).start(self.period)

    def _calc_temp(self, r):
        To = 298.15
        B = 3977.
        Ro = 10000.
        try:
            temp_c = (1/((1/To)+(1/B)*log(r/Ro))) - 272.15
            temp_f = temp_c*1.8 + 32.
            #print [r, temp_c, temp_f]
            return temp_f
        except:
            return r
